package com.lightsh.db;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.util.Log;

import com.lightsh.common.CharacterItem;
import com.lightsh.common.NoteItem;
import com.lightsh.common.PaintItem;
import com.lightsh.common.PaintStroke;
import com.lightsh.utility.ByteUtil;
import com.lightsh.utility.Constants;
import com.lightsh.utility.Utility;

public class DbDataHelper {
	private static final String TAG = "DbDataHelper";
	private static final boolean DEBUG = Constants.DEBUG;
	
	public static final boolean getNoteCharacterList(Context context, long id, ArrayList<CharacterItem> list){
		MyDbHelper db = new MyDbHelper(context);
		try{
			Cursor cursor = db.getNoteCharacter(id);
			if(cursor != null){
	        	try{
	        		if(cursor.moveToFirst()){
	        			int idColumn = cursor.getColumnIndex(MyDbHelper.CHARACTER_FIELD_ID);
	        			int keyColumn = cursor.getColumnIndex(MyDbHelper.CHARACTER_FIELD_KEY);
	        			int indexColumn = cursor.getColumnIndex(MyDbHelper.CHARACTER_FIELD_INDEX);
	        			int bmColumn = cursor.getColumnIndex(MyDbHelper.CHARACTER_FIELD_BITMAP);
	        			while(true){
	        				byte[] bmByte = cursor.getBlob(bmColumn);
	        				CharacterItem item = new CharacterItem(BitmapFactory.decodeByteArray(bmByte, 0, bmByte.length));
	        				item.mId = cursor.getLong(idColumn);
	        				item.mKey = cursor.getLong(keyColumn);
	        				item.mIndex = cursor.getInt(indexColumn);
	        				list.add(item);
	        				if(!cursor.moveToNext()){
	        					break;
	        				}
	        			}
	            	}
	        		return true;
	        	}finally{
	        		cursor.close();
	        	}
	        }else{
	        	Log.w(Constants.TAG, "get character fail, id = " + id);
	        }
			
		}finally{
			if(db != null){
				db.close();
			}
		}
		return false;
	}
	public static final boolean getPaintStrokeList(Context context, long id, List<PaintStroke> list){
		MyDbHelper db = new MyDbHelper(context);
		try{
			Cursor cursor = db.getPaintStroke(id);
			if(cursor != null){
	        	try{
	        		if(cursor.moveToFirst()){
	        			int colorColumn = cursor.getColumnIndex(MyDbHelper.STROKE_FIELD_COLOR);
	        			int typeColumn = cursor.getColumnIndex(MyDbHelper.STROKE_FIELD_TYPE);
	        			int widthColumn = cursor.getColumnIndex(MyDbHelper.STROKE_FIELD_STROKE_WIDTH);
	        			int pointsColumn = cursor.getColumnIndex(MyDbHelper.STROKE_FIELD_POINTS);
	        			PaintStroke ps;
	        			while(true){
	        				byte[] pointsByte = cursor.getBlob(pointsColumn);
	        				float[] strokePoints = ByteUtil.getFloatArray(pointsByte);
	        				ps = PaintStroke.newInstance(strokePoints, cursor.getInt(colorColumn), 
	        						cursor.getInt(typeColumn), cursor.getInt(widthColumn));
	        				list.add(ps);
	        				if(!cursor.moveToNext()){
	        					break;
	        				}
	        			}
	            	}
	        		return true;
	        	}finally{
	        		cursor.close();
	        	}
	        }else{
	        	Log.w(Constants.TAG, "get stroke fail, id = " + id);
	        }
			
		}finally{
			if(db != null){
				db.close();
			}
		}
		return false;
	}
	
	
	public static void getAllNotesList(Context context, List<NoteItem> targetList){
		MyDbHelper db = new MyDbHelper(context);
		try{
			Cursor cursor = db.fetchAllNoteDataOrderbyTime();
			if(cursor != null){
	        	try{
	        		if(cursor.moveToFirst()){
	        			int [] columnIndexs = getNoteColumnIndexs(cursor);      			
	        			while(true){
	        				targetList.add(parseNoteInfo(columnIndexs, cursor));
	        				if(!cursor.moveToNext()){
	        					break;
	        				}
	        			}
	            	}
	        	}finally{
	        		cursor.close();
	        	}
	        }
		}finally{
			if(db != null){
				db.close();
			}
		}
	}
	public static void getAllPaintList(Context context, List<PaintItem> targetList){
		MyDbHelper db = new MyDbHelper(context);
		try{
			Cursor cursor = db.fetchAllPaintOrderbyTime();
			if(cursor != null){
	        	try{
	        		if(cursor.moveToFirst()){
	        			int [] columnIndexs = getPaintColumnIndexs(cursor);      			
	        			while(true){
	        				targetList.add(parsePaintInfo(columnIndexs, cursor));
	        				if(!cursor.moveToNext()){
	        					break;
	        				}
	        			}
	            	}
	        	}finally{
	        		cursor.close();
	        	}
	        }
		}finally{
			if(db != null){
				db.close();
			}
		}
	}
	
	/**
	 * 查询指定的note信息，查询不到返回null
	 */
	public static NoteItem getNoteInfo(Context context, long noteId){
		NoteItem item = null;
		MyDbHelper db = new MyDbHelper(context);
		try{
			Cursor cursor = db.fetchNoteData(noteId);
			if(cursor != null){
	        	try{
	        		if(cursor.moveToFirst()){
	        			item = parseNoteInfo(cursor);
	            	}
	        	}finally{
	        		cursor.close();
	        	}
	        }
		}finally{
			if(db != null){
				db.close();
			}
		}
		return item;
	}
	private static NoteItem parseNoteInfo(Cursor cursor){
		return parseNoteInfo(getNoteColumnIndexs(cursor), cursor);
	}
	private static int[] getNoteColumnIndexs(Cursor cursor){
		int idColumn = cursor.getColumnIndex(MyDbHelper.NOTE_FIELD_ID);
		int keyColumn = cursor.getColumnIndex(MyDbHelper.NOTE_FIELD_KEY);
		int timeColumn = cursor.getColumnIndex(MyDbHelper.NOTE_FIELD_TIME);	  
		int textColumn = cursor.getColumnIndex(MyDbHelper.NOTE_FIELD_TEXT);	
		int createTimeColumn = cursor.getColumnIndex(MyDbHelper.NOTE_FIELD_CREATE_TIME);	
		return new int[]{idColumn, keyColumn, timeColumn, textColumn, createTimeColumn};
	}
	private static NoteItem parseNoteInfo(int[] columnIndexs, Cursor cursor){
		return new NoteItem(cursor.getInt(columnIndexs[0]), cursor.getString(columnIndexs[1]), 
				cursor.getLong(columnIndexs[2]), cursor.getString(columnIndexs[3]), cursor.getLong(columnIndexs[4]));
	}
	/**
	 * find specify paint by id
	 * @return	null if not found
	 */
	public static PaintItem getPaintInfo(Context context, long id){
		PaintItem item = null;
		MyDbHelper db = new MyDbHelper(context);
		try{
			Cursor cursor = db.fetchPaintData(id);
	        try{
	        	if(cursor.moveToFirst()){
	        		item = parsePaintInfo(cursor);
	            }
	        }finally{
	        	cursor.close();
	        }
		}finally{
			if(db != null){
				db.close();
			}
		}
		return item;
	}
	private static PaintItem parsePaintInfo(Cursor cursor){
		return parsePaintInfo(getPaintColumnIndexs(cursor), cursor);
	}
	private static int[] getPaintColumnIndexs(Cursor cursor){
		int idColumn = cursor.getColumnIndex(MyDbHelper.PAINT_FIELD_ID);
		int textColumn = cursor.getColumnIndex(MyDbHelper.PAINT_FIELD_TEXT);
		int typeColumn = cursor.getColumnIndex(MyDbHelper.PAINT_FIELD_TYPE);	  
		int timeColumn = cursor.getColumnIndex(MyDbHelper.PAINT_FIELD_TIME);	
		int createTimeColumn = cursor.getColumnIndex(MyDbHelper.PAINT_FIELD_CREATE_TIME);	
		int widthColumn = cursor.getColumnIndex(MyDbHelper.PAINT_FIELD_WIDTH);	
		int heightColumn = cursor.getColumnIndex(MyDbHelper.PAINT_FIELD_HEIGHT);	
		return new int[]{idColumn, textColumn, typeColumn, timeColumn, createTimeColumn, widthColumn, heightColumn};
	}
	private static PaintItem parsePaintInfo(int[] columnIndexs, Cursor cursor){
		return new PaintItem(cursor.getLong(columnIndexs[0]), 
				cursor.getString(columnIndexs[1]), 
				cursor.getLong(columnIndexs[3]), 
				cursor.getLong(columnIndexs[4]), 
				cursor.getInt(columnIndexs[5]), cursor.getInt(columnIndexs[6]));
	}
	
	/**
	 * 保存/更新note信息
	 * @param context
	 * @param oldId		如果id为非{@link NoteItem#INVALID_ID},表示需要更新旧信息
	 * @param text
	 * @param list
	 * @return	是否保存/更新成功
	 */
	public static boolean saveNoteInfo(Context context, long oldId, String text, List<CharacterItem> list){
		MyDbHelper db = new MyDbHelper(context);
		try{
			final long time = System.currentTimeMillis();
			if(oldId != NoteItem.INVALID_ID){
				// delete all old character and update note's time
				db.deleteCharactersByNote(oldId);
				if(!db.updateNoteData(oldId, text, time)){
        			logE("update id " + oldId + " time and text fail!");
        		}
			}else{
				oldId = db.insertNoteData("", 0, text, time, time);
				if(oldId == NoteItem.INVALID_ID){
					logE("insert note data fail !");
					return false;
				}
			}
			int i = 0;
			for(CharacterItem item : list){
				try{
        			byte[] bmByte = Utility.bitmapToPNGBytes(item.mBitmap);
            		if(bmByte != null){
            			if(db.insertCharacterData(oldId, i, bmByte) == -1){
            				logE("save " + i + " bm fail!");
            				continue;
            			}
            		}
        		}catch(Exception e){
        			e.printStackTrace();
        		}
        		i++;
			}
			return true;
		}finally{
			db.close();
		}
	}
	/**
	 * 保存/更新paint信息
	 * @param context
	 * @param oldId		如果id为非{@link NoteItem#INVALID_ID},表示需要更新旧信息
	 * @param text
	 * @param list
	 * @return	是否保存/更新成功
	 */
	public static boolean savePaintInfo(Context context, long oldId, String text, 
			int width, int height, List<PaintStroke> list){
		MyDbHelper db = new MyDbHelper(context);
		try{
			final long time = System.currentTimeMillis();
			if(oldId != PaintItem.INVALID_ID){
				// delete all old stroke and update paint's time
				db.deleteStrokeByPaint(oldId);
				if(!db.updatePaintData(oldId, text, time)){
        			logE("update paint id = " + oldId + " time and text fail!");
        		}
			}else{
				oldId = db.insertPaintData(text, PaintItem.PAINT_TYPE_NORMAL, time, time, width, height);
				if(oldId == PaintItem.INVALID_ID){
					logE("insert paint data fail !");
					return false;
				}
			}
			int i = 0;
			for(PaintStroke item : list){
				try{
					if(db.insertStrokesData(oldId, i, item.getColor(), item.getType(), 
							item.getWidth(), item.getStrokePoints()) == -1){
						logE("save " + i + " stroke fail!");
						continue;
					}
        		}catch(Exception e){
        			e.printStackTrace();
        		}
        		i++;
			}
			return true;
		}finally{
			db.close();
		}
	}
	private static void logE(String tip){
    	Log.e(TAG, "" + tip); 	
    }
}
